package com.hp.common.common;


import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

/**
 * 统一的API返回接口
 *
 * @author xavierdong
 **/
public class Result<T> implements Serializable {


    private static final long serialVersionUID = -7700068701296006425L;
    /**
     * 响应码
     */
    private String code;

    /**
     * 消息
     */
    private String msg;

    /**
     * 响应体
     */
    private T data;

    /**
     * 时间
     */
    private String date;


    /**
     * 请求id
     */
    private String requestId;

    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");

    public Result() {
    }

    /**
     * 使用了类上面那个注解，在这种情况下，只返回code，不会有msg和data
     *
     * @param code
     */
    public Result(String code, String date) {
        this.code = code;
        this.date = date;
        this.requestId = UUID.randomUUID().toString();

    }

    public Result(String code, String msg, String date) {
        this.code = code;
        this.msg = msg;
        this.date = date;
        this.requestId = UUID.randomUUID().toString();
    }

    public Result(String code, T data, String date) {
        this.code = code;
        this.date = date;
        this.data = data;
        this.requestId = UUID.randomUUID().toString();
    }

    public Result(String code, String msg, T data, String date) {
        this.code = code;
        this.date = date;
        this.msg = msg;
        this.data = data;
        this.requestId = UUID.randomUUID().toString();
    }

    /**
     * 在json序列化时，该字段不会显示在json里面 使之不在json序列化结果当中
     *
     * @return
     */
    public boolean isSuccess() {
        return this.code.equals(ResponseCode.SUCCESS.getCode());
    }

    public String getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }

    public T getData() {
        return data;
    }

    public String getDate() {
        return date;
    }

    public String getRequestId() {
        return requestId;
    }

    /**
     * 成功，返回一个code
     *
     * @param <T>
     * @return
     */
    public static <T> Result<T> createBySuccess() {
        return new Result<>(ResponseCode.SUCCESS.getCode(), formatter.format(LocalDateTime.now()));
    }

    /**
     * 成功，返回一个文本供前端提示使用
     *
     * @param msg
     * @param <T>
     * @return
     */
    public static <T> Result<T> createBySuccessMessage(String msg) {
        return new Result<>(ResponseCode.SUCCESS.getCode(), msg, formatter.format(LocalDateTime.now()));
    }

    /**
     * 成功，返回对应的数据
     *
     * @param data
     * @param <T>
     * @return
     */
    public static <T> Result<T> createBySuccess(T data) {
        return new Result<>(ResponseCode.SUCCESS.getCode(), data, formatter.format(LocalDateTime.now()));
    }

    /**
     * 成功，把消息和数据都返回
     *
     * @param msg
     * @param data
     * @param <T>
     * @return
     */
    public static <T> Result<T> createBySuccess(String msg, T data) {
        return new Result<>(ResponseCode.SUCCESS.getCode(), msg, data, formatter.format(LocalDateTime.now()));
    }

    /**
     * 失败，返回一个code
     *
     * @param <T>
     * @return
     */
    public static <T> Result<T> createByError() {
        return new Result<>(ResponseCode.BAD_REQUEST.getCode(), ResponseCode.BAD_REQUEST.getDesc(), formatter.format(LocalDateTime.now()));
    }

    /**
     * 失败，返回一个文本供前端提示使用
     *
     * @param errorMessage
     * @param <T>
     * @return
     */
    public static <T> Result<T> createByErrorMessage(String errorMessage) {
        return new Result<>(ResponseCode.BAD_REQUEST.getCode(), errorMessage, formatter.format(LocalDateTime.now()));
    }

    /**
     * 失败，返回对应的数据
     *
     * @param data
     * @param <T>
     * @return
     */
    public static <T> Result<T> createByError(String errorCode, T data) {
        return new Result<>(errorCode, data, formatter.format(LocalDateTime.now()));
    }

    /**
     * 失败，返回一个status和提示
     *
     * @param errorCode
     * @param errorMessage
     * @param <T>
     * @return
     */
    public static <T> Result<T> createByErrorCodeMessage(String errorCode, String errorMessage) {
        return new Result<>(errorCode, errorMessage, formatter.format(LocalDateTime.now()));
    }

    /**
     * 失败，返回提示
     *
     * @param errorCode
     * @param data
     * @param <T>
     * @return
     */
    public static <T> Result<T> createByErrorData(String errorCode, T data) {
        return new Result<>(errorCode, data, formatter.format(LocalDateTime.now()));

    }

    public enum ResponseCode {

        // 常用的 code 码
        SUCCESS("200", "SUCCESS"),
        BAD_REQUEST("400", "Bad Request"),
        UNAUTHORIZED("401", "Unauthorized"),
        LARGE_FILE("402", "Maximum upload size exceeded"),
        FORBIDDEN("403", "Forbidden"),
        NOT_FOUND("404", "Not Found"),
        INTERNAL_SERVER_ERROR("500", "Unknown Internal Error"),
        // 以下为 业务定义的 code 码
        ERROR_SIGNATURE("10000", "Error Signature"),
        PRECONDITION_FAILED("10001", "Precondition Failed"),
        NOT_VALID_PARAM("10002", "Not valid Params"),
        NOT_SUPPORTED_OPERATION("10003", "Operation not supported"),
        NOT_LOGIN("10004", "Not Login"),
        BAD_CREDENTIALS("10005", "Bad credentials"),
        USER_DISABLED("10006", "User is disabled"),
        NOT_VALID_TOKEN("10007", "Not Valid TOKEN"),
        TOKEN_EXPIRED("10008", "Token Expired"),
        NOT_TOKEN("10009", "NOT TOKEN"),
        ACCOUNT_LOCKED("10010", "User account is locked"),
        CREDENTIALS_EXPIRED("10011", "User credentials have expired"),
        VERIFICATION_TIMEOUT("10012", "verification timed out"),
        ILLEGAL_ARGUMENT("10013", "illegal argument"),
        UPLOAD_EXCEPTION("10014", "upload file exception");


        private final String code;
        private final String desc;


        ResponseCode(String code, String desc) {
            this.code = code;
            this.desc = desc;
        }

        public String getCode() {
            return code;
        }

        public String getDesc() {
            return desc;
        }

    }
}
